//
//  NSObject+MDHNSObject.m
//  JSTech
//
//  Created by 高得华 on 2019/4/24.
//  Copyright © 2020 华&梅. All rights reserved.
//

#import "NSObject+MDHNSObject.h"
#if __has_include(<MJExtension/MJExtension.h>)
#import <MJExtension/MJExtension.h>
#else
#import "MJExtension.h"
#endif
#import <objc/runtime.h>
#import "MDHMacroHeader.h"
///本地资源解密
#import "RNDecryptor.h"

@implementation NSObject (MDHNSObject)

///Hook进行修改 字体的大小
+ (void)load {
    ///字体方面
    ///系统
    Method fontSysOld = class_getClassMethod(UIFont.class, @selector(systemFontOfSize:));
    Method fontSysNew = class_getClassMethod(self, @selector(hook_systemFontOfSize:));
    method_exchangeImplementations(fontSysOld, fontSysNew);
    ///名字
    Method fontNameOld = class_getClassMethod(UIFont.class, @selector(fontWithName:size:));
    Method fontNameNew = class_getClassMethod(self, @selector(hook_fontWithName:size:));
    method_exchangeImplementations(fontNameOld, fontNameNew);
    ///italicSystem
    Method fontItalicOld = class_getClassMethod(UIFont.class, @selector(italicSystemFontOfSize:));
    Method fontItalicNew = class_getClassMethod(self, @selector(hook_italicSystemFontOfSize:));
    method_exchangeImplementations(fontItalicOld, fontItalicNew);
    ///BoldSystem
    Method fontBoldSystemOld = class_getClassMethod(UIFont.class, @selector(boldSystemFontOfSize:));
    Method fontBoldSystemNew = class_getClassMethod(self, @selector(hook_boldSystemFontOfSize:));
    method_exchangeImplementations(fontBoldSystemOld, fontBoldSystemNew);
}


///Hook进行修改 字体的大小
///系统的
+ (UIFont *)hook_systemFontOfSize:(CGFloat)fontSize {
    return [UIFont hook_systemFontOfSize:fontSize*kMDHPTAutoScale()];
}
+ (UIFont *)hook_fontWithName:(NSString *)fontName size:(CGFloat)fontSize {
    return [UIFont hook_fontWithName:fontName size:fontSize*kMDHPTAutoScale()];
}
+ (UIFont *)hook_italicSystemFontOfSize:(CGFloat)fontSize {
    return [UIFont hook_italicSystemFontOfSize:fontSize*kMDHPTAutoScale()];
}
+ (UIFont *)hook_boldSystemFontOfSize:(CGFloat)fontSize {
    return [UIFont hook_boldSystemFontOfSize:fontSize*kMDHPTAutoScale()];
}


//MARK: - ===== MHExtension 👇👇👇👇👇👇
+ (NSInteger) mh_randomNumberWithFrom:(NSInteger)from to:(NSInteger)to{
    return (NSInteger)(from + (arc4random() % (to - from + 1)));
}

- (void)mh_convertNotification:(NSNotification *)notification completion:(void (^ _Nullable)(CGFloat, UIViewAnimationOptions, CGFloat))completion
{
    // 按钮
    NSDictionary *userInfo = notification.userInfo;
    // 最终尺寸
    CGRect endFrame = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    // 开始尺寸
    CGRect beginFrame = [userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue];
    // 动画时间
    CGFloat duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    /// options
    UIViewAnimationOptions options = ([userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue] << 16 ) | UIViewAnimationOptionBeginFromCurrentState;
    
    /// keyboard height
    CGFloat keyboardH = 0;
    if (beginFrame.origin.y == [[UIScreen mainScreen] bounds].size.height){
        // up
        keyboardH = endFrame.size.height;
    }else if (endFrame.origin.y == [[UIScreen mainScreen] bounds].size.height) {
        // down
        keyboardH = 0;
    }else{
        // up
        keyboardH = endFrame.size.height;
    }
    /// 回调
    !completion?:completion(duration,options,keyboardH);
}



/// Get class
- (BOOL)mh_isStringClass { return [self isKindOfClass:[NSString class]]; }
- (BOOL)mh_isNumberClass { return [self isKindOfClass:[NSNumber class]]; }
- (BOOL)mh_isArrayClass { return [self isKindOfClass:[NSArray class]]; }
- (BOOL)mh_isDictionaryClass { return [self isKindOfClass:[NSDictionary class]]; }
- (BOOL)mh_isStringOrNumberClass { return [self mh_isStringClass] || [self mh_isNumberClass]; }
- (BOOL)mh_isNullOrNil { return !self || [self isKindOfClass:[NSNull class]]; }
- (BOOL)mh_isExist {
    if (self.mh_isNullOrNil) return NO;
    if (self.mh_isStringClass) return (self.mh_stringValueExtension.length>0);
    return YES;
}

/// Get value
- (NSString *)mh_stringValueExtension{
    if ([self mh_isStringClass]) return [(NSString *)self length]? (NSString *)self: @"";
    if ([self mh_isNumberClass]) return [NSString stringWithFormat:@"%@", self];
    return @"";
}


+ (id)loadInfo:(Class)aclass withKey:(NSString *)key
{
    NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
    NSString *loginInfo = [ud objectForKey:key];
    if (loginInfo)
    {
        id ret = [[aclass class] mj_objectWithKeyValues:loginInfo];
        if (ret)
        {
            return ret;
        }
        else
        {
            return loginInfo;
        }
    }
    return @"";
}


+ (void)saveInfo:(NSObject *)obj withKey:(NSString *)key
{
    NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
    if (obj)
    {
        if ([obj isKindOfClass:[NSString class]])
        {
            [ud setObject:obj forKey:key];
        }
        else
        {
            NSDictionary *dic = [obj mj_JSONObject];
            
            if ([NSJSONSerialization isValidJSONObject:dic])
            {
                NSError *error = nil;
                NSData *data = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:&error];
                if(error)
                {
                    DTLog(@"存储失败");
                }
                NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
                [ud setObject:str forKey:key];
            }
        }
        
        [ud synchronize];
    }
    else
    {
        [ud removeObjectForKey:key];
    }
}
//MARK: - ===== MHExtension 👆👆👆👆👆👆


@end






@implementation NSObject (CommonBlock)

- (void)excuteBlock:(CommonBlock)block
{
    __weak id selfPtr = self;
    if (block) {
        block(selfPtr);
    }
}

- (void)performBlock:(CommonBlock)block
{
    if (block)
    {
        [self performSelector:@selector(excuteBlock:) withObject:block];
    }
}

- (void)performBlock:(CommonBlock)block afterDelay:(NSTimeInterval)delay
{
    if (block)
    {
        [self performSelector:@selector(excuteBlock:) withObject:block afterDelay:delay];
    }
}

- (void)cancelPerformBlock:(CommonBlock)block {
    if (block) {
        [[self class] cancelPreviousPerformRequestsWithTarget:self selector:@selector(excuteBlock:) object:block];
        //[self cancelPreviousPerformRequestsWithTarget:self selector:@selector(excuteBlock:) object:block];
    }
}

- (void)cancelBlock:(CommonBlock)block
{
    [[NSRunLoop currentRunLoop] cancelPerformSelector:@selector(excuteBlock:) target:self argument:block];
}


- (void)excuteCompletion:(CommonCompletionBlock)block withFinished:(NSNumber *)finished
{
    __weak id selfPtr = self;
    if (block) {
        block(selfPtr, finished.boolValue);
    }
}

- (void)performCompletion:(CommonCompletionBlock)block withFinished:(BOOL)finished
{
    if (block)
    {
        [self performSelector:@selector(excuteCompletion:withFinished:) withObject:block withObject:[NSNumber numberWithBool:finished]];
    }
}

- (void)cancelCompletion:(CommonCompletionBlock)block
{
    [[NSRunLoop currentRunLoop] cancelPerformSelector:@selector(excuteCompletion:withFinished:) target:self argument:block];
}

//- (void)performCompletion:(CommonCompletionBlock)block withFinished:(BOOL)finished afterDelay:(NSTimeInterval)delay
//{
//    if (block)
//    {
//        self performSelector:<#(SEL)#> withObject:<#(id)#> afterDelay:<#(NSTimeInterval)#>
////        [self performSelector:@selector(excuteCompletion:withFinished:) withObject:block withObject:[NSNumber numberWithBool:finished] afterDelay:delay];
//    }
//}

- (void)asynExecuteCompletion:(CommonBlock)completion tasks:(CommonBlock)task, ... NS_REQUIRES_NIL_TERMINATION
{
    va_list arguments;
    
    if (task)
    {
        if (task)
        {
            dispatch_async(dispatch_get_global_queue(0, 0), ^{
                if (task)
                {
                    task(self);
                }
            });
            
            va_start(arguments, task);
            DTLog(@"%@ <<<<<<<<<=============", task);
            BOOL next = YES;
            do
            {
                CommonBlock eachObject = va_arg(arguments, CommonBlock);
                DTLog(@"%@ <<<<<<<<<=============", eachObject);
                if (eachObject)
                {
                    dispatch_async(dispatch_get_global_queue(0, 0), ^{
                        if (eachObject)
                        {
                            eachObject(self);
                        }
                    });
                }
                else
                {
                    next = NO;
                }
                
            }while (next);
            va_end(arguments);
        }
        
        
        
        
        dispatch_barrier_async(dispatch_get_global_queue(0, 0), ^{
            if (completion)
            {
                completion(self);
            }
        });
    }
}
@end






//MARK: - ===== UIViewController
@implementation UIViewController (MDHUIViewController)
@end


//MARK: - ===== UIScrollView
@implementation UIScrollView (MDHUIScrollView)
/// 添加下拉刷新控件
- (MJRefreshStateHeader *)mh_addHeaderRefresh:(void(^)(MJRefreshStateHeader *header))refreshingBlock {
    @weakify(self);
    MJRefreshGifHeader *mj_header = [MJRefreshGifHeader headerWithRefreshingBlock:^{
        @strongify(self);
        !refreshingBlock?:refreshingBlock((MJRefreshStateHeader *)self.mj_header);
    }];
    /*MJRefreshNormalHeader *mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
        @strongify(self);
        !refreshingBlock?:refreshingBlock((MJRefreshStateHeader *)self.mj_header);
    }];
    mj_header.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;*/
    //mj_header.labelLeftInset = 100;
    mj_header.lastUpdatedTimeLabel.hidden = true;
    // Configure normal mj_header
    self.mj_header = mj_header;
    mj_header.stateLabel.hidden = true;
    // 设置正在刷新状态的动画图片
    NSMutableArray *refreshingImages = [NSMutableArray array];
    for (int i = 1; i<=13; i++) {
        UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"refresh_%02d", i+1]];
        if (image) {
            [refreshingImages addObject:image];
        }
    }
    [mj_header setImages:refreshingImages forState: MJRefreshStateRefreshing];
    [mj_header setImages:refreshingImages forState: MJRefreshStateIdle];
    [mj_header setImages:refreshingImages forState: MJRefreshStatePulling];
    return mj_header;
}

/// 添加上拉加载控件
- (MJRefreshAutoStateFooter *)mh_addFooterRefresh:(void(^)(MJRefreshAutoStateFooter *footer))refreshingBlock {
    @weakify(self);
    MJRefreshAutoNormalFooter *mj_footer = [MJRefreshAutoNormalFooter footerWithRefreshingBlock:^{
        @strongify(self);
        !refreshingBlock?:refreshingBlock((MJRefreshAutoStateFooter *)self.mj_footer);
    }];
    // Configure normal mj_footer
    [mj_footer setTitle:@"别拉了，已经到底了..." forState:MJRefreshStateNoMoreData];
    self.mj_footer = mj_footer;
    
    /*
     mj_footer.refreshingTitleHidden = true;
     // 设置正在刷新状态的动画图片
     NSMutableArray *refreshingImages = [NSMutableArray array];
     for (NSUInteger i = 1; i<=4; i++) {
     UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"refresh_%zd", i]];
     if (image) {
     [refreshingImages addObject:image];
     }
     }
     [mj_footer setImages:refreshingImages forState: MJRefreshStateRefreshing];
     [mj_footer setImages:refreshingImages forState: MJRefreshStateIdle];
     [mj_footer setImages:refreshingImages forState: MJRefreshStatePulling];
     */
    
    return mj_footer;
}
@end




@implementation UIColor (MDHColor)


+ (UIColor *)colorWithHexStr:(NSString *)color alpha:(CGFloat)alpha {
    //删除字符串中的空格
    NSString *cString = [[color
                          stringByTrimmingCharactersInSet:[NSCharacterSet
                                                           whitespaceAndNewlineCharacterSet]]
                         uppercaseString];
    // String should be 6 or 8 characters
    if ([cString length] < 6) {
        return [UIColor clearColor];
    }
    // strip 0X if it appears
    //如果是0x开头的，那么截取字符串，字符串从索引为2的位置开始，一直到末尾
    if ([cString hasPrefix:@"0X"]) {
        cString = [cString substringFromIndex:2];
    }
    //如果是#开头的，那么截取字符串，字符串从索引为1的位置开始，一直到末尾
    if ([cString hasPrefix:@"#"]) {
        cString = [cString substringFromIndex:1];
    }
    if ([cString length] != 6) {
        return [UIColor clearColor];
    }
    
    // Separate into r, g, b substrings
    NSRange range;
    range.location = 0;
    range.length = 2;
    // r
    NSString *rString = [cString substringWithRange:range];
    // g
    range.location = 2;
    NSString *gString = [cString substringWithRange:range];
    // b
    range.location = 4;
    NSString *bString = [cString substringWithRange:range];
    
    // Scan values
    unsigned int r, g, b;
    [[NSScanner scannerWithString:rString] scanHexInt:&r];
    [[NSScanner scannerWithString:gString] scanHexInt:&g];
    [[NSScanner scannerWithString:bString] scanHexInt:&b];
    return [UIColor colorWithRed:((float)r / 255.0f)
                           green:((float)g / 255.0f)
                            blue:((float)b / 255.0f)
                           alpha:alpha];
}



@end



//MARK: - ===== NSDate

// Always keep the formatter around as they're expensive to instantiate
static NSDateFormatter *_internetDateTimeFormatter = nil;

// A category to parse internet date & time strings
@implementation NSDate (MDHDate)


// Instantiate single date formatter
+ (NSDateFormatter *)internetDateTimeFormatter {
    @synchronized(self) {
        if (!_internetDateTimeFormatter) {
            NSLocale *en_US_POSIX = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
            _internetDateTimeFormatter = [[NSDateFormatter alloc] init];
            [_internetDateTimeFormatter setLocale:en_US_POSIX];
            [_internetDateTimeFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
        }
    }
    return _internetDateTimeFormatter;
}

// Get a date from a string - hint can be used to speed up
+ (NSDate *)dateFromInternetDateTimeString:(NSString *)dateString formatHint:(MDHDateFormatHint)hint {
     // Keep dateString around a while (for thread-safety)
    NSDate *date = nil;
    if (dateString) {
        if (hint != MDHDateFormatHintRFC3339) {
            // Try RFC822 first
            date = [NSDate dateFromRFC822String:dateString];
            if (!date) date = [NSDate dateFromRFC3339String:dateString];
        } else {
            // Try RFC3339 first
            date = [NSDate dateFromRFC3339String:dateString];
            if (!date) date = [NSDate dateFromRFC822String:dateString];
        }
    }
     // Finished with date string
    return date;
}

// See http://www.faqs.org/rfcs/rfc822.html
+ (NSDate *)dateFromRFC822String:(NSString *)dateString {
     // Keep dateString around a while (for thread-safety)
    NSDate *date = nil;
    if (dateString) {
        NSDateFormatter *dateFormatter = [NSDate internetDateTimeFormatter];
        @synchronized(dateFormatter) {

            // Process
            NSString *RFC822String = [[NSString stringWithString:dateString] uppercaseString];
            if ([RFC822String rangeOfString:@","].location != NSNotFound) {
                if (!date) { // Sun, 19 May 2002 15:21:36 GMT
                    [dateFormatter setDateFormat:@"EEE, d MMM yyyy HH:mm:ss zzz"];
                    date = [dateFormatter dateFromString:RFC822String];
                }
                if (!date) { // Sun, 19 May 2002 15:21 GMT
                    [dateFormatter setDateFormat:@"EEE, d MMM yyyy HH:mm zzz"];
                    date = [dateFormatter dateFromString:RFC822String];
                }
                if (!date) { // Sun, 19 May 2002 15:21:36
                    [dateFormatter setDateFormat:@"EEE, d MMM yyyy HH:mm:ss"];
                    date = [dateFormatter dateFromString:RFC822String];
                }
                if (!date) { // Sun, 19 May 2002 15:21
                    [dateFormatter setDateFormat:@"EEE, d MMM yyyy HH:mm"];
                    date = [dateFormatter dateFromString:RFC822String];
                }
            } else {
                if (!date) { // 19 May 2002 15:21:36 GMT
                    [dateFormatter setDateFormat:@"d MMM yyyy HH:mm:ss zzz"];
                    date = [dateFormatter dateFromString:RFC822String];
                }
                if (!date) { // 19 May 2002 15:21 GMT
                    [dateFormatter setDateFormat:@"d MMM yyyy HH:mm zzz"];
                    date = [dateFormatter dateFromString:RFC822String];
                }
                if (!date) { // 19 May 2002 15:21:36
                    [dateFormatter setDateFormat:@"d MMM yyyy HH:mm:ss"];
                    date = [dateFormatter dateFromString:RFC822String];
                }
                if (!date) { // 19 May 2002 15:21
                    [dateFormatter setDateFormat:@"d MMM yyyy HH:mm"];
                    date = [dateFormatter dateFromString:RFC822String];
                }
            }
            if (!date) NSLog(@"Could not parse RFC822 date: \"%@\" Possible invalid format.", dateString);
            
        }
    }
     // Finished with date string
    return date;
}

// See http://www.faqs.org/rfcs/rfc3339.html
+ (NSDate *)dateFromRFC3339String:(NSString *)dateString {
     // Keep dateString around a while (for thread-safety)
    NSDate *date = nil;
    if (dateString) {
        NSDateFormatter *dateFormatter = [NSDate internetDateTimeFormatter];
        @synchronized(dateFormatter) {
            
            // Process date
            NSString *RFC3339String = [[NSString stringWithString:dateString] uppercaseString];
            RFC3339String = [RFC3339String stringByReplacingOccurrencesOfString:@"Z" withString:@"-0000"];
            // Remove colon in timezone as it breaks NSDateFormatter in iOS 4+.
            // - see https://devforums.apple.com/thread/45837
            if (RFC3339String.length > 20) {
                RFC3339String = [RFC3339String stringByReplacingOccurrencesOfString:@":"
                                                                         withString:@""
                                                                            options:0
                                                                              range:NSMakeRange(20, RFC3339String.length-20)];
            }
            if (!date) { // 1996-12-19T16:39:57-0800
                [dateFormatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ssZZZ"];
                date = [dateFormatter dateFromString:RFC3339String];
            }
            if (!date) { // 1937-01-01T12:00:27.87+0020
                [dateFormatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss.SSSZZZ"];
                date = [dateFormatter dateFromString:RFC3339String];
            }
            if (!date) { // 1937-01-01T12:00:27
                [dateFormatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss"];
                date = [dateFormatter dateFromString:RFC3339String];
            }
            if (!date) NSLog(@"Could not parse RFC3339 date: \"%@\" Possible invalid format.", dateString);
            
        }
    }
     // Finished with date string
    return date;
}

@end




//MARK: - ===== UIImage
// A category to parse internet date & time strings
@implementation UIImage (MDHImage)

+ (NSBundle *)dh_bundle {
    static NSBundle *hxBundle = nil;
    if (hxBundle == nil) {
        NSString *path = [[NSBundle mainBundle] pathForResource:@"MDHPTSource" ofType:@"bundle"];
        if (!path) {
            path = [[NSBundle mainBundle] pathForResource:@"MDHPTSource" ofType:@"bundle" inDirectory:@"Frameworks/MDHPTFramework.framework/"];
        }
        hxBundle = [NSBundle bundleWithPath:path];
    }
    return hxBundle;
}

///图片的路径
+ (NSString *)dh_bundle_decrypt_path:(NSString *)imageName {
    NSBundle *myBundle = [UIImage dh_bundle];
    imageName = [[@"Other/" stringByAppendingString:imageName] stringByAppendingString:@".mdhpt"];
    NSString * path_file = [myBundle pathForResource:imageName ofType:@""];
    return path_file;
}

///获取图片
+ (UIImage *_Nullable)imageNamed_dh:(NSString *_Nullable)name {
    return [UIImage imageNamed_dh:name decrypt:false];
}

///获取是否加密的图片
+ (UIImage *_Nullable)imageNamed_dh:(NSString *_Nullable)name decrypt:(BOOL)isDecrypt {
    if (name.length <= 0) {
        return nil;
    }
    if (isDecrypt) {
        return [UIImage cxyTopngWithImageName:name];
    }
    UIImage *image = [self imageNamed:name];;
    if (image) return image;
    NSBundle *myBundle = [UIImage dh_bundle];
    name = [name stringByAppendingString:@"@2x"];
    NSString *imagePath = [myBundle pathForResource:name ofType:@"png"];
    image = [self imageWithContentsOfFile:imagePath];
    if (image) {
        return image;
    } else {
        name = [name stringByReplacingOccurrencesOfString:@"@2x" withString:@""];
        image = [self imageNamed:name];
        return image;
    }
}

///解密
+ (UIImage *)cxyTopngWithImageName:(NSString *)imageName {
    NSString * path_file = [UIImage dh_bundle_decrypt_path:imageName];
    NSData *encryptedData = [NSData dataWithContentsOfFile:path_file];
    NSError *error;
    NSData *decryptedData = [RNDecryptor decryptData:encryptedData
                                        withPassword:@"mdhpt_huamei"
                                               error:&error];
    return [UIImage imageWithData:decryptedData];
}


///压缩图片 到指定的大小
+ (UIImage *)compressImageQuality:(UIImage *)image toByte:(NSInteger)maxLength {
    CGFloat compression = 1;
    NSData *data = UIImageJPEGRepresentation(image, compression);
    if (data.length < maxLength) return image;
    CGFloat max = 1;
    CGFloat min = 0;
    for (int i = 0; i < 6; ++i) {
        compression = (max + min) / 2;
        data = UIImageJPEGRepresentation(image, compression);
        if (data.length < maxLength * 0.9) {
            min = compression;
        } else if (data.length > maxLength) {
            max = compression;
        } else {
            break;
        }
    }
    UIImage *resultImage = [UIImage imageWithData:data];
    return resultImage;
}


+ (UIImage *)sd_animatedGIFWithData:(NSData *)data {
    if (!data) {
        return nil;
    }

    CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);

    size_t count = CGImageSourceGetCount(source);

    UIImage *animatedImage;

    if (count <= 1) {
        animatedImage = [[UIImage alloc] initWithData:data];
    }
    else {
        NSMutableArray *images = [NSMutableArray array];

        NSTimeInterval duration = 0.0f;

        for (size_t i = 0; i < count; i++) {
            CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL);
            if (!image) {
                continue;
            }

            duration += [self sd_frameDurationAtIndex:i source:source];

            [images addObject:[UIImage imageWithCGImage:image scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]];

            CGImageRelease(image);
        }

        if (!duration) {
            duration = (1.0f / 10.0f) * count;
        }

        animatedImage = [UIImage animatedImageWithImages:images duration:duration];
    }

    CFRelease(source);

    return animatedImage;
}

+ (float)sd_frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source {
    float frameDuration = 0.1f;
    CFDictionaryRef cfFrameProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil);
    NSDictionary *frameProperties = (__bridge NSDictionary *)cfFrameProperties;
    NSDictionary *gifProperties = frameProperties[(NSString *)kCGImagePropertyGIFDictionary];

    NSNumber *delayTimeUnclampedProp = gifProperties[(NSString *)kCGImagePropertyGIFUnclampedDelayTime];
    if (delayTimeUnclampedProp) {
        frameDuration = [delayTimeUnclampedProp floatValue];
    }
    else {

        NSNumber *delayTimeProp = gifProperties[(NSString *)kCGImagePropertyGIFDelayTime];
        if (delayTimeProp) {
            frameDuration = [delayTimeProp floatValue];
        }
    }

    // Many annoying ads specify a 0 duration to make an image flash as quickly as possible.
    // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify
    // a duration of <= 10 ms. See <rdar://problem/7689300> and <http://webkit.org/b/36082>
    // for more information.

    if (frameDuration < 0.011f) {
        frameDuration = 0.100f;
    }

    CFRelease(cfFrameProperties);
    return frameDuration;
}

+ (UIImage *)sd_animatedGIFNamed:(NSString *)name {
    CGFloat scale = [UIScreen mainScreen].scale;

    if (scale > 1.0f) {
        NSString *retinaPath = [[NSBundle mainBundle] pathForResource:[name stringByAppendingString:@"@2x"] ofType:@"gif"];

        NSData *data = [NSData dataWithContentsOfFile:retinaPath];

        if (data) {
            return [UIImage sd_animatedGIFWithData:data];
        }

        NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@"gif"];

        data = [NSData dataWithContentsOfFile:path];

        if (data) {
            return [UIImage sd_animatedGIFWithData:data];
        }

        return [UIImage imageNamed:name];
    }
    else {
        NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@"gif"];

        NSData *data = [NSData dataWithContentsOfFile:path];

        if (data) {
            return [UIImage sd_animatedGIFWithData:data];
        }

        return [UIImage imageNamed:name];
    }
}

- (UIImage *)sd_animatedImageByScalingAndCroppingToSize:(CGSize)size {
    if (CGSizeEqualToSize(self.size, size) || CGSizeEqualToSize(size, CGSizeZero)) {
        return self;
    }

    CGSize scaledSize = size;
    CGPoint thumbnailPoint = CGPointZero;

    CGFloat widthFactor = size.width / self.size.width;
    CGFloat heightFactor = size.height / self.size.height;
    CGFloat scaleFactor = (widthFactor > heightFactor) ? widthFactor : heightFactor;
    scaledSize.width = self.size.width * scaleFactor;
    scaledSize.height = self.size.height * scaleFactor;

    if (widthFactor > heightFactor) {
        thumbnailPoint.y = (size.height - scaledSize.height) * 0.5;
    }
    else if (widthFactor < heightFactor) {
        thumbnailPoint.x = (size.width - scaledSize.width) * 0.5;
    }

    NSMutableArray *scaledImages = [NSMutableArray array];

    for (UIImage *image in self.images) {
        UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
        
        [image drawInRect:CGRectMake(thumbnailPoint.x, thumbnailPoint.y, scaledSize.width, scaledSize.height)];
        UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();

        [scaledImages addObject:newImage];

        UIGraphicsEndImageContext();
    }
 
    return [UIImage animatedImageWithImages:scaledImages duration:self.duration];
}




@end
